package com.lframework.jh.push.core.components.aop;

import com.lframework.jh.push.core.annotations.OpenApi;
import com.lframework.jh.push.core.components.sign.CheckSignFactory;
import com.lframework.jh.push.core.components.sign.CheckSignHandler;
import com.lframework.jh.push.core.exceptions.impl.AccessDeniedException;
import com.lframework.jh.push.core.utils.ApplicationUtil;
import com.lframework.jh.push.core.utils.ArrayUtil;
import com.lframework.jh.push.core.utils.CollectionUtil;
import com.lframework.jh.push.core.vo.OpenApiReqVo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * OpenApi切面
 *
 * @author zmj
 */
@Aspect
public class OpenApiAspect {

    @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)) && @annotation(com.lframework.jh.push.core.annotations.OpenApi) && execution(public * *(..))")
    public void openApiPointCut() {

    }

    @Around(value = "openApiPointCut()")
    public Object openApi(ProceedingJoinPoint joinPoint) throws Throwable {

        Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        OpenApi openApi = signature.getMethod().getAnnotation(OpenApi.class);

        Object[] args = joinPoint.getArgs();

        if (openApi.sign()) {
            CheckSignFactory checkSignFactory = ApplicationUtil.getBean(CheckSignFactory.class);
            CheckSignHandler checkSignHandler = checkSignFactory.getInstance();

            if (ArrayUtil.isEmpty(args)) {
                throw new AccessDeniedException("验签失败！");
            }
            List<OpenApiReqVo> reqList = Arrays.stream(args).filter(t -> t instanceof OpenApiReqVo)
                    .map(t -> (OpenApiReqVo) t).collect(Collectors.toList());

            if (CollectionUtil.isEmpty(reqList)) {
                throw new AccessDeniedException("验签失败！");
            }
            for (OpenApiReqVo req : reqList) {
                if (!checkSignHandler.check(req)) {
                    throw new AccessDeniedException("验签失败！");
                }
            }
        }

        Object value = joinPoint.proceed();

        return value;
    }
}
